package mail

import (
	"bytes"
	"crypto/tls"
	"errors"
	"html/template"
	"time"

	"gitee.com/huangxinbo/xcas/internal/config"
	"gitee.com/huangxinbo/xcas/pkg/i18n"
	"gitee.com/huangxinbo/xcas/pkg/logger"
	"go.uber.org/zap"
	"gopkg.in/gomail.v2"
)

type Mail struct {
	config    *config.Config
	logger    *logger.Logger
	i18n      *i18n.I18n
	templates map[string]*template.Template
}

// RenderData 模板渲染数据
type RenderData struct {
	Subject     string
	Title       string
	CurrentYear string
	ToEmail     string
	Data        any
}

func NewMail(logger *logger.Logger, config *config.Config, i18n *i18n.I18n) *Mail {
	mailRenderer := NewMailTemplates(logger, config, i18n)
	mailRenderer.GetTemplates()
	return &Mail{
		config:    config,
		logger:    logger,
		i18n:      i18n,
		templates: mailRenderer.templates,
	}
}

// newDialer creates a new gomail dialer from configuration
func (mail *Mail) newDialer() *gomail.Dialer {
	d := gomail.NewDialer(
		mail.config.Mail.Host,
		mail.config.Mail.Port,
		mail.config.Mail.Username,
		mail.config.Mail.Password,
	)
	d.TLSConfig = &tls.Config{
		InsecureSkipVerify: true,
		ServerName:         mail.config.Mail.Host,
	}
	return d
}

// SendHTMLEmail sends an HTML email
func (mail *Mail) SendHTMLEmail(toEmail, subject, htmlBody string) error {
	if mail.config.Mail.Host == "" || mail.config.Mail.Username == "" || mail.config.Mail.Password == "" {
		mail.logger.Warn("Mail configuration is incomplete, skipping email sending")
		return nil
	}

	// Create message
	m := gomail.NewMessage()
	m.SetHeader("From", mail.config.Mail.From)
	m.SetHeader("To", toEmail)
	m.SetHeader("Subject", subject)
	m.SetBody("text/html", htmlBody)

	// Send email
	dialer := mail.newDialer()
	if err := dialer.DialAndSend(m); err != nil {
		mail.logger.Error("Failed to send HTML email", zap.Error(err), zap.String("to", toEmail))
		return err
	}

	return nil
}

func (mail *Mail) SendEmail(templateName string, data RenderData) error {
	if tmpl, ok := mail.templates[templateName]; ok {
		// 执行模板渲染
		var buf bytes.Buffer
		err := tmpl.ExecuteTemplate(&buf, "layout", mail.addDefaultData(data))
		if err != nil {
			mail.logger.Error("Failed to execute template",
				zap.String("template", templateName),
				zap.Error(err))
			return nil
		}

		return mail.SendHTMLEmail(data.ToEmail, data.Subject, buf.String())
	}
	return errors.New("template not found: " + templateName)
}

// addDefaultData 补充默认数据
func (mail *Mail) addDefaultData(data RenderData) RenderData {
	data.Title = mail.config.Server.Name
	data.CurrentYear = time.Now().Format("2006")
	return data
}

func (mail *Mail) ClearCache() {
	mail.templates = make(map[string]*template.Template)
}
